﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Twodi.Structs
{
    /// <summary>
    /// Modelo de contador regressivo.
    /// </summary>
    public class RegressiveTimer : Timer
    {
        /// <summary>
        /// Tempo restante para finalizar o contador.
        /// </summary>
        protected TimeSpan remaining;

        /// <summary>
        /// Tempo de contagem regressiva.
        /// </summary>
        protected TimeSpan countdown;

        /// <summary>
        /// Contador finalizado.
        /// </summary>
        protected bool isFinished;

        /// <summary>
        /// Auto resetar contador ao finalizar.
        /// </summary>
        protected bool autoReset;

        /// <summary>
        /// Construtor padrão.
        /// </summary>
        public RegressiveTimer()
        {
            FinishedChanged += new EventHandler<EventArgs>(InvokeFinished);
            Finished += new EventHandler<EventArgs>(AutoResetTimer);
            RemaniningChanged += new EventHandler<EventArgs>(ValidateFinished);
        }

        /// <summary>
        /// Verificar se remaining chegou ao ponto critico (TimeSpan.Zero).
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void ValidateFinished(object sender, EventArgs e)
        {
            if (Remanining <= TimeSpan.Zero && !IsFinished)
            {
                IsFinished = true;
            }
        }

        /// <summary>
        /// Autoo resetar timer.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void AutoResetTimer(object sender, EventArgs e)
        {
            if (AutoReset)
            {
                Reset();
            }
        }

        /// <summary>
        /// Invocar finished ao terminar.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void InvokeFinished(object sender, EventArgs e)
        {
            if (IsFinished)
            {
                Enabled = false;
                onFinished(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Atualizar contador regressivo.
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
            //Contabilizar timer.
            base.Update(gameTime);

            //Calcular tempo restante.
            this.CalculateRemaining();
        }

        /// <summary>
        /// Reiniciar contagem regressiva.
        /// </summary>
        public virtual void Reset()
        {
            this.Enabled = true;
            this.Time = TimeSpan.Zero;
            this.IsFinished = false;
            onReseted(EventArgs.Empty);
        }

        /// <summary>
        /// Calcular tempo restante.
        /// </summary>
        protected virtual void CalculateRemaining()
        {
            Remanining = Countdown - Time;
        }

        /// <summary>
        /// Tempo restante para finalizar o contador.
        /// </summary>
        public TimeSpan Remanining
        {
            get { return this.remaining; }
            set
            {
                this.remaining = value;
                onRemaniningChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Tempo de contagem regressiva.
        /// </summary>
        public TimeSpan Countdown
        {
            get { return this.countdown; }
            set
            {
                this.countdown = value;
                onCountdownChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Contador finalizado.
        /// </summary>
        public bool IsFinished
        {
            get { return this.isFinished; }
            set
            {
                this.isFinished = value;
                onFinishedChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Auto resetar contador ao finalizar.
        /// </summary>
        public bool AutoReset
        {
            get { return this.autoReset; }
            set
            {
                this.autoReset = value;
                onAutoResetChanged(EventArgs.Empty);
            }
        }

        /// <summary>
        /// Evento invocado quando tempo restante é alterado.
        /// </summary>
        public event EventHandler<EventArgs> RemaniningChanged;

        /// <summary>
        /// Evento invocado quando tempo de contagem regressiva é alterado.
        /// </summary>
        public event EventHandler<EventArgs> CountdownChanged;

        /// <summary>
        /// Evento invocado quando tempo de contagem regressiva é alterado.
        /// </summary>
        public event EventHandler<EventArgs> FinishedChanged;

        /// <summary>
        /// Evento invocado quando contador finaliza sua contagem.
        /// </summary>
        public event EventHandler<EventArgs> Finished;

        /// <summary>
        /// Evento invocado quando auto resetar é alterado..
        /// </summary>
        public event EventHandler<EventArgs> AutoResetChanged;

        /// <summary>
        /// Evento invocado quando componente reseta.
        /// </summary>
        public event EventHandler<EventArgs> Reseted;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="e"></param>
        protected virtual void onRemaniningChanged(EventArgs e)
        {
            if (RemaniningChanged != null)
            {
                RemaniningChanged(this, e);
            }
        }

        protected virtual void onCountdownChanged(EventArgs e)
        {
            if (CountdownChanged != null)
            {
                CountdownChanged(this, e);
            }
        }

        protected virtual void onFinishedChanged(EventArgs e)
        {
            if (FinishedChanged != null)
            {
                FinishedChanged(this, e);
            }
        }

        protected virtual void onFinished(EventArgs e)
        {
            if (Finished != null)
            {
                Finished(this, e);
            }
        }

        protected virtual void onAutoResetChanged(EventArgs e)
        {
            if (AutoResetChanged != null)
            {
                AutoResetChanged(this, e);
            }
        }

        protected virtual void onReseted(EventArgs e)
        {
            if (Reseted != null)
            {
                Reseted(this, e);
            }
        }
    }
}
